package com.beiding.render;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;

//通用的标签解析工具
public class ULabel {

    public List<Label> toLabel(List<Pair> pairs,String type) {
        return toLabel(pairs, (a, b) -> true, type);
    }

    public interface Filter {
        boolean filter(Pair pair, Label label);
    }

    public List<Label> toLabel(List<Pair> pairs, Filter filter, String type) {

        List<Label> labels = new ArrayList<>();
        Label label = new Label();
        for (Pair pair : pairs) {
            if (filter.filter(pair, label)) {
                //排序依据
                label.sort = pair.blockStart.start;
                label.type = type;
                label.holder = pair.holder;
                label.body = pair.body;
                label.name = this.tagName;
                label.commands = pair.blockStart.commands;
                label.attributes = pair.blockStart.attributes;
                label.handlers = pair.blockStart.handlers;
                labels.add(label);
                label = new Label(); //避免内存浪费
            }
        }
        return labels;
    }


    //将内部所有节点处理成树
    private void pairToTree(List<Pair> pairs) {

        //同级节点过

        for (Pair pair : pairs) {
            pairToTree(pair, pairs);
            if (pair.toRootInners.size() > 0) {
                //递归处理
                pairToTree(pair.toRootInners);
            }
        }

    }

    //将区块处理成 树状结构  第一个参数为比对参照 pairs 中 含于 第一个参数的复制一份作为第一个参数的 toRootInners
    private void pairToTree(Pair pair, List<Pair> pairs) {
        int s = pair.blockStart.start;
        int e = pair.blockEnd.end;
        List<Pair> inner = new ArrayList<>();
        for (Pair p : pairs) {
            //内部节点包含所有元素
            if (p.hierarchy > pair.hierarchy && s < p.blockStart.start && p.blockEnd.end < e) {
                Pair clonePair = cloneRefPair(p, pair);
                inner.add(clonePair);
            }
        }
        pair.toRootInners = inner;
    }

    //节点复制
    private Pair cloneRefPair(Pair p, Pair reference) {

        int s = reference.blockStart.end;
        Pair c = new Pair();
        Pair.BlockStart blockStart = new Pair.BlockStart();
        Pair.BlockEnd blockEnd = new Pair.BlockEnd();

        blockStart.start = p.blockStart.start - s;
        blockStart.end = p.blockStart.end - s;
        blockStart.attributes = p.blockStart.attributes;
        blockStart.handlers = p.blockStart.handlers;

        blockStart.commands = p.blockStart.commands;
        blockEnd.start = p.blockEnd.start - s;
        blockEnd.end = p.blockEnd.end - s;

        c.blockEnd = blockEnd;
        c.blockStart = blockStart;

        c.body = p.body;

        //减去根节点的层级接口
        c.hierarchy = p.hierarchy - reference.hierarchy - 1;

        return c;
    }

    public void setTagName(String tagName) {
        this.tagName = tagName;
    }

    //解析成对,层级为0的为最外层节点
    List<Pair> parsePairs(String s) {

        List<Pair.BlockStart> starts = new ArrayList<>();

        int from = 0;

        while (true) {
            ContentUtils.StartTagMsg startBlock = ContentUtils.findStart(s, tagName, from);
            if (startBlock == null) {
                break;
            }

            Pair.BlockStart blockStart = new Pair.BlockStart();
            blockStart.start = startBlock.start;
            blockStart.end = startBlock.end;

            //移除掉参数绑定和处理器映射
            for (String k : startBlock.attributes.keySet()) {
                String v = startBlock.attributes.get(k);
                if (k.startsWith(":")) {
                    if (v != null) {
                        k = k.substring(1);
                        blockStart.attributes.put(k, v.trim());
                        startBlock.attributes.remove(k);
                    }
                } else if (k.startsWith("_")) {
                    if (v != null) {
                        k = k.substring(1);
                        blockStart.handlers.put(k, v.trim());
                        startBlock.attributes.remove(k);
                    }
                }
            }

            //其余的为指令
            blockStart.commands = startBlock.attributes;
            blockStart.noBody = startBlock.noBody;

            starts.add(blockStart);
            from = startBlock.end;
            if (from == s.length()) {
                break;
            }
        }

        List<Pair.BlockEnd> ends = new LinkedList<>();


        //搜索结束标签
        from = 0;
        while (true) {
            ContentUtils.EndTagMsg endTagMsg = ContentUtils.findEnd(s, tagName, from);
            if (endTagMsg == null) {
                break;
            }

            Pair.BlockEnd blockEnd = new Pair.BlockEnd();
            blockEnd.start = endTagMsg.start;
            blockEnd.end = endTagMsg.end;

            ends.add(blockEnd);
            from = endTagMsg.end;
            if (from == s.length()) {
                break;
            }
        }

        //将开始标签和结束标签配对
        List<Pair.BlockTag> tags = new ArrayList<>();

        tags.addAll(starts);
        tags.addAll(ends);

        List<Pair> pairList = new ArrayList<>();

        if (tags.size() > 0) {

            Pair.BlockTag blockTag = tags.get(0);
            if (!(blockTag instanceof Pair.BlockStart)) {
                throw new RuntimeException("块节点中开始结束标签不匹配");
            }
            tags.sort((a, b) -> a.start - b.end);
            Stack<Pair> pairs = new Stack<>();

            for (Pair.BlockTag tag : tags) {
                if (tag instanceof Pair.BlockStart) {
                    Pair pair = new Pair();
                    pair.blockStart = (Pair.BlockStart) tag;
                    pair.hierarchy = pairs.size();

                    if (pair.blockStart.noBody) {
                        Pair.BlockEnd blockEnd = new Pair.BlockEnd();

                        //TODO 放入一个空白的标签
                        blockEnd.start = pair.blockStart.end;
                        blockEnd.end = pair.blockStart.end;
                        pair.blockEnd = blockEnd;
                        pair.body = s.substring(pair.blockStart.end, pair.blockEnd.start);
                        pairList.add(pair);
                    } else {
                        pairs.push(pair);
                    }
                } else {
                    Pair pop = pairs.pop();
                    if (pop == null) {
                        throw new RuntimeException("块节点中开始结束标签不匹配");
                    }
                    pop.blockEnd = (Pair.BlockEnd) tag;
                    //体
                    pop.body = s.substring(pop.blockStart.end, pop.blockEnd.start);
                    pairList.add(pop);
                }
            }

            if (pairs.size() != 0) {
                throw new RuntimeException("块节点中开始结束标签不匹配");
            }
        }

        //处理成树状结构
        pairToTree(pairList);

        return pairList;

    }

    private String tagName;

    ULabel(String tagName) {
        this.tagName = tagName;
    }

    //将区块替换成占位符
    String replaceHolder(String s, List<Pair> pairs) {

        StringBuilder builder = new StringBuilder();

        int end = 0;

        //开始
        for (Pair pair : pairs) {
            if (pair.hierarchy == 0) {
                builder.append(s, end, pair.blockStart.start);
                String id = ContentUtils.createHolder();
                builder.append(id);
                end = pair.blockEnd.end;
                pair.holder = id;
            }
        }

        if (end <= s.length() - 1) {
            builder.append(s.substring(end));
        }
        return builder.toString();
    }


/*
    public static void main(String[] args) {

        String s = "<tp name=\"丁常磊\"><tp dd/></tp>";

        ULabel uLabel = new ULabel("tp");

        List<Expression> pairs = uLabel.parsePairs(s);

        for (Expression pair : pairs) {
            System.out.println(pair);
        }

    }
*/


}
